package com.ctfo.ulcp.exp.server

import com.ctfo.ulcp.exp.core.PyCaller
import com.ctfo.ulcp.exp.db.Users
import com.ctfo.ulcp.exp.db.createJDBCPool
import com.ctfo.ulcp.exp.db.runTx
import com.ctfo.ulcp.exp.db.LLMModel
import io.vertx.core.json.Json
import io.vertx.ext.web.Router
import io.vertx.jdbcclient.JDBCPool
import io.vertx.kotlin.coroutines.CoroutineVerticle
import io.vertx.kotlin.coroutines.await
import kotlinx.coroutines.future.await
import kotlinx.coroutines.launch
import org.slf4j.LoggerFactory


class ServiceServer : CoroutineVerticle() {

    private val logger = LoggerFactory.getLogger("main")
    private lateinit var pool: JDBCPool


    override suspend fun start() {
        val httpServer = vertx.createHttpServer()
        val router = Router.router(vertx)
        pool = createJDBCPool(vertx)


        httpServer.requestHandler(router).listen(8888).onComplete { ar ->
            if (ar.failed()) {
                logger.error("HTTP server start failed")
                ar.cause().printStackTrace()
                vertx.close()
            }
        }

        router.get("/a").handler { ctx ->
            launch {
                val t0 = System.currentTimeMillis()
                val answer = PyCaller.callQuestion(LLMModel.OpenAI, userInput = "请介绍一下千方科技").await()
                ctx.response().putHeader("content-type", "application/json")
                    .end("time: ${System.currentTimeMillis() - t0}, answer:$answer")
            }
        }



        router.get("/find").handler { ctx ->
            val id = ctx.queryParams()["id"]
            launch {
                try {
                    val rows = pool.query("SELECT * FROM t_user where id= $id").execute().await()
                    ctx.response().putHeader("content-type", "application/json").end(rows!!.first()!!.toJson().encode())
                } catch (e: Exception) {
                    e.printStackTrace()
                    ctx.response().setStatusCode(500).end("Failed to retrieve data")
                }
            }
        }

        router.get("/find2").handler { ctx ->
            val id = ctx.queryParams()["id"]
            launch {
                val user = Users.find(Integer.valueOf(id))
                ctx.response().putHeader("content-type", "application/json").end(Json.encodeToBuffer(user))
            }
        }


        router.get("/all").handler { ctx ->
            pool.query("SELECT * FROM t_user").execute { ar ->
                if (ar.succeeded()) {
                    val result = ar.result()
                    ctx.json(result!!.map { it.toJson() })
                } else {
                    logger.error("error:", ar.cause())
                    ctx.response().setStatusCode(500).end("Failed to retrieve data")
                }
            }
        }

        router.get("/delete").handler { ctx ->
            pool.withTransaction { conn ->
                conn.query("delete from t_user")
                    .execute()
            }.onSuccess { v ->
                println("Transaction succeeded")
                ctx.response().setStatusCode(200).end("Transaction succeeded")
            }.onFailure { err: Throwable ->
                println("Transaction failed: " + err.message)
                ctx.response().setStatusCode(500).end("Transaction failed: " + err.message)
            }
        }



        router.get("/add").handler { ctx ->
            pool.withTransaction { conn ->
                conn.query("INSERT INTO test (name) VALUES ('add1')")
                    .execute()
                    .compose { res ->
                        conn.query("INSERT INTO test (id,name) VALUES (17,'add2')").execute()
                    }
            }.onSuccess { v ->
                println("Transaction succeeded")
                ctx.response().setStatusCode(200).end("Transaction succeeded")
            }.onFailure { err: Throwable ->
                logger.error("Transaction failed: ", err)
                ctx.response().setStatusCode(500).end("Transaction failed: " + err.message)
            }
        }

        router.get("/add2").handler { ctx ->
            launch {
                try {
                    runTx(pool) { conn ->
                        conn.query("INSERT INTO test (name) VALUES ('test111')").execute().await()
                        conn.query("INSERT INTO test (id,name) VALUES (1,'test2222')").execute().await()
                    }
                    ctx.response().setStatusCode(200).end("Transaction succeeded")
                } catch (err: Exception) {
                    logger.error("Transaction failed: ", err)
                    ctx.response().setStatusCode(500).end("Transaction failed: " + err.message)
                }
            }

        }


    }
}